#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 8888
#define BACKLOG 5
#define BUF_SIZE 200

char buf[BUF_SIZE];
int conn_amount;

void show_client() {
    printf("client amount: %d\n", conn_amount);
}

void handle_conn(int connsocket) {
    while (1) {
        int ret = recv(connsocket, buf, sizeof(buf), 0); // 从该socket读取数据
        if (ret <= 0) {
            printf("client %d close\n", connsocket);
            conn_amount--;
            close(connsocket);
            show_client();
            break;
        } else {
            if (ret < BUF_SIZE) {
                memset(buf + ret, '\0', 1);
            }
            printf("client %d send: %s\n", connsocket, buf);
        }
    }
}

int main(void) {
    int sockfd, newconn_fd; // 分别定义监听和成功连接后新的socket
    struct sockaddr_in server_addr; // 服务器IP地址
    struct sockaddr_in client_addr; // 客户端的IP地址
    socklen_t sin_size;
    int yes = 1;
    int pid, ppid;

    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("socket failed");
        exit(1);
    }

    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) < 0) {
        perror("setsockopt failed");
        exit(1);
    }

    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(PORT);
    server_addr.sin_addr.s_addr = INADDR_ANY; // 自动绑定本机IP地址
    memset(server_addr.sin_zero, 0, sizeof(server_addr.sin_zero));

    if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        perror("bind error");
        exit(1);
    }

    if (listen(sockfd, BACKLOG) < 0) {
        perror("listen error");
        exit(1);
    }

    printf("listening at port %d\n", PORT);
    conn_amount = 0; // 连接数
    sin_size = sizeof(client_addr);

    while (1) {
        newconn_fd = accept(sockfd, NULL, NULL); // 等待客户请求
        if (newconn_fd <= 0) {
            perror("accept error");
            printf("the newconn fd is %d\n", newconn_fd);
            continue;
        } else {
            conn_amount++;
            show_client();
            pid = fork();
            if (pid < 0) {
                perror("fork failed");
                exit(1);
            } else if (pid == 0) { // 子进程
                ppid = fork();
                if (ppid < 0) {
                    perror("fork failed");
                    exit(1);
                } else if (ppid == 0) { // 子进程的子进程
                    handle_conn(newconn_fd); // 处理连接请求
                    close(sockfd);
                }
            }
        }
    }
}